# 雪花算法生成器（用于生成商户订单号）
import time
import threading

class SnowflakeGenerator:
    """雪花算法生成器（生成64位唯一ID）"""
    def __init__(self, worker_id: int = 0, datacenter_id: int = 0):
        # 常量定义
        self.worker_id_bits = 5
        self.datacenter_id_bits = 5
        self.sequence_bits = 12

        # 最大取值限制
        self.max_worker_id = -1 ^ (-1 << self.worker_id_bits)  # 31
        self.max_datacenter_id = -1 ^ (-1 << self.datacenter_id_bits)  # 31

        # 移位偏移量
        self.worker_id_shift = self.sequence_bits  # 12
        self.datacenter_id_shift = self.sequence_bits + self.worker_id_bits  # 17
        self.timestamp_shift = self.sequence_bits + self.worker_id_bits + self.datacenter_id_bits  # 22

        # 序号掩码
        self.sequence_mask = -1 ^ (-1 << self.sequence_bits)  # 4095

        # 初始化参数（确保worker_id和datacenter_id在合法范围）
        if worker_id > self.max_worker_id or worker_id < 0:
            raise ValueError(f"worker_id必须在0-{self.max_worker_id}之间")
        if datacenter_id > self.max_datacenter_id or datacenter_id < 0:
            raise ValueError(f"datacenter_id必须在0-{self.max_datacenter_id}之间")
        
        self.worker_id = worker_id
        self.datacenter_id = datacenter_id
        self.last_timestamp = -1  # 上次生成ID的时间戳
        self.sequence = 0  # 序列号（同一毫秒内递增）
        self.lock = threading.Lock()  # 线程锁（确保并发安全）

    def _gen_timestamp(self) -> int:
        """生成当前毫秒级时间戳"""
        return int(time.time() * 1000)

    def generate_id(self) -> int:
        """生成雪花ID"""
        with self.lock:
            timestamp = self._gen_timestamp()

            # 处理时钟回拨（若当前时间小于上次时间，说明时钟回拨）
            if timestamp < self.last_timestamp:
                raise RuntimeError(f"时钟回拨，拒绝生成ID：{self.last_timestamp - timestamp}毫秒")

            # 同一毫秒内，序列号递增
            if timestamp == self.last_timestamp:
                self.sequence = (self.sequence + 1) & self.sequence_mask
                # 序列号溢出（同一毫秒生成超过4096个ID）
                if self.sequence == 0:
                    # 等待下一毫秒
                    while timestamp <= self.last_timestamp:
                        timestamp = self._gen_timestamp()
            else:
                # 不同毫秒，序列号重置为0
                self.sequence = 0

            # 更新上次时间戳
            self.last_timestamp = timestamp

            # 拼接64位ID：符号位（1）+ 时间戳（41）+ 数据中心ID（5）+ 工作节点ID（5）+ 序列号（12）
            snowflake_id = (
                (timestamp << self.timestamp_shift)
                | (self.datacenter_id << self.datacenter_id_shift)
                | (self.worker_id << self.worker_id_shift)
                | self.sequence
            )
            return snowflake_id

# 初始化雪花生成器（worker_id和datacenter_id根据部署环境配置（不同人这两个数字不一样,worker_id在1-30），确保分布式唯一）
# 同一数据中心内的 worker_id 必须唯一，不同数据中心的 worker_id 可以重复
# worker_id 工作节点ID，datacenter_id 数据中心ID，二者限制范围为0-31
snowflake = SnowflakeGenerator(worker_id=1, datacenter_id=1)

# 生成一个雪花ID
id = snowflake.generate_id()
print('===',id)